﻿#ifndef TL_STRING_H
#define TL_STRING_H

#include <iostream>
#include "TL_Status.h"


/*
КОДЫ ОШИБОК:
1 - неизвестная ошибка
2 - 
*/


namespace TL {
    /* TL::String */

    class String {
    private:
        char *m_String;
        unsigned int m_Size;

    private:
        char *Copy(const char *string);
        char *Copy(const char *string, unsigned int string_length);

    public:
        String();
        String(const char *string);
        String(const String &string);
        ~String();

    public:
        const char *GetCharString();
        unsigned int Size();

    public:
        const char *operator()();
        String operator=(const char *string);
        String operator=(const String &string);
        friend bool operator==(const char *left_string, const String &right_string);
        friend bool operator==(const String &left_string, const char *right_string);
        friend bool operator==(const String &left_string, const String &right_string);
        friend std::ostream &operator<<(std::ostream &stream, String &string);
    };

    char *String::Copy(const char *string)
    {
        char *newString;
        unsigned int string_length = strlen(string);

        if(string_length) {
            newString = new char [string_length+1];
            strcpy(newString, string);
            newString[string_length] = '\0';
        }

        return newString;
    }

    char *String::Copy(const char *string, unsigned int string_length)
    {
        char *newString;

        if(string_length) {
            newString = new char [string_length+1];
            strcpy(newString, string);
            newString[string_length] = '\0';
        }

        return newString;
    }

    String::String()
    {
        m_String = 0;
        m_Size = 0;
    }

    String::String(const char *string)
    {
        m_Size = strlen(string);

        m_String = m_Size ? Copy(string, m_Size) : 0;
    }

    String::String(const String &string)
    {
        if(string.m_Size) {
            m_String = Copy(string.m_String, string.m_Size);
            m_Size = string.m_Size;
        } else {
            m_String = 0;
            m_Size = 0;
        }
    }

    String::~String()
    {
        if(m_Size) {
            delete [] m_String;
        }
    }

    const char *String::GetCharString()
    {
        return m_String;
    }

    unsigned int String::Size()
    {
        return m_Size;
    }

    const char *String::operator()()
    {
        return m_String;
    }

    String String::operator=(const char *string)
    {
        unsigned int string_length = strlen(string);

        if(m_Size && string_length) {
            if(m_Size != string_length) {
                delete [] m_String;

                m_String = Copy(string, string_length);
            } else {
                strcpy(m_String, string);
            }
        } else if(!m_Size && string_length) {
            m_String = Copy(string, string_length);
        } else if(m_Size && !string_length) {
            delete [] m_String;

            m_String = 0;
        }

        m_Size = string_length;

        return *this;
    }

    String String::operator=(const String &string)
    {
        if(m_Size && string.m_Size) {
            if(m_Size != string.m_Size) {
                delete [] m_String;

                m_String = Copy(string.m_String, string.m_Size);
            } else {
                strcpy(m_String, string.m_String);
            }
        } else if(!m_Size && string.m_Size) {
            m_String = Copy(string.m_String, string.m_Size);
        } else if(m_Size && !string.m_Size) {
            delete [] m_String;

            m_String = 0;
        }

        m_Size = string.m_Size;

        return *this;
    }

    bool operator==(const char *left_string, const String &right_string)
    {
        return !strcmp(left_string, right_string.m_String);
    }

    bool operator==(const String &left_string, const char *right_string)
    {
        return !strcmp(left_string.m_String, right_string);
    }

    bool operator==(const String &left_string, const String &right_string)
    {
        return !strcmp(left_string.m_String, right_string.m_String);
    }

    std::ostream &operator<<(std::ostream &stream, String &string)
    {
        if(string.m_Size) {
            stream << string.m_String;
        }

        return stream;
    }
}

#endif